package cn.jtfadmin.base.doc.swagger;

import com.thoughtworks.qdox.JavaProjectBuilder;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaMethod;
import com.thoughtworks.qdox.model.JavaType;
import io.swagger.annotations.ApiImplicitParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.method.HandlerMethod;
import springfox.documentation.RequestHandler;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.OperationBuilderPlugin;
import springfox.documentation.spi.service.contexts.OperationContext;
import springfox.documentation.spi.service.contexts.RequestMappingContext;
import springfox.documentation.swagger.common.SwaggerPluginSupport;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;


@Component
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER)
public class DocOperationNotesReader implements OperationBuilderPlugin {
    private final JavaProjectBuilder javaProjectBuilder;
    @Autowired
    public DocOperationNotesReader( JavaProjectBuilder javaProjectBuilder) {
        this.javaProjectBuilder = javaProjectBuilder;
    }

    @Override
    public void apply(OperationContext context) {
        try{
            Field f1 = ReflectionUtils.findField(context.getClass(), "requestContext");
            ReflectionUtils.makeAccessible(f1);
            RequestMappingContext requestMappingContext = (RequestMappingContext) f1.get(context);
            Field f2 = ReflectionUtils.findField(RequestMappingContext.class, "handler");
            ReflectionUtils.makeAccessible(f2);
            RequestHandler requestHandler = (RequestHandler) f2.get(requestMappingContext);
            HandlerMethod handlerMethod = requestHandler.getHandlerMethod();
            if(handlerMethod!=null){
                Method method = handlerMethod.getMethod();
                Class<?> c = method.getDeclaringClass();
                String name = method.getName();
                Class<?>[] genericParameterTypes = method.getParameterTypes();
                JavaClass javaClass = javaProjectBuilder.getClassByName(c.getName());
                if(javaClass!=null){
                    List<JavaMethod> methods =
                            javaClass.getMethods(true);
                    for (JavaMethod javaMethod : methods) {
                        boolean match = true;
                        if(!javaMethod.getName().equals(name)){
                            match = false;
                        }
                        List<JavaType> parameterTypes = javaMethod.getParameterTypes();
                        if(match){
                            if(parameterTypes.size() != genericParameterTypes.length){
                                match = false;
                            }
                        }
                        for (int i = 0; i < parameterTypes.size(); i++) {
                            if(! parameterTypes.get(i).getFullyQualifiedName().equals(genericParameterTypes[i].getName())){
                                match = false;
                                break;
                            }

                        }
                        if(match){
                            context.operationBuilder().summary(javaMethod.getComment())
                                .notes(javaMethod.getComment());
                        }

                    }
                }
            }
        }catch (Exception e){
        }

    }

    @Override
    public boolean supports(DocumentationType delimiter) {
        return SwaggerPluginSupport.pluginDoesApply(delimiter);
    }
}
